package com.gjy.sb2.advice;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gjy.sb2.annotation.Encrypt;
import com.gjy.sb2.domain.AjaxResult;
import com.gjy.sb2.sm.SmUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;
import java.util.Map;

/**
 * @author gjy
 * @version 1.0
 * @since 2025-07-08 09:09:02
 */
@RestControllerAdvice
public class Sm2EncryptAdvice implements ResponseBodyAdvice<AjaxResult> {
    private static final Logger log = LoggerFactory.getLogger(Sm2EncryptAdvice.class);

    @Value("${sm2.pubK}")
    private String pubK;
    @Value("${sm2.priK}")
    private String priK;

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> cls) {
        return methodParameter.hasMethodAnnotation(Encrypt.class);
    }

    @Override
    public AjaxResult beforeBodyWrite(AjaxResult ar, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> cls, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ObjectMapper om = new ObjectMapper();
            String s = om.writeValueAsString(ar);
            String encrypt = SmUtil.sm2Encrypt(pubK, s);
            String sign = SmUtil.sm2Sign(priK, s);
            ajaxResult.setCode(ar.getCode());
            ajaxResult.setMsg(ar.getMsg());
            Map<String, String> map = new HashMap<>();
            map.put("sign", sign);
            map.put("encrypt", encrypt);
            ajaxResult.setData(map);
        } catch (Exception e) {
            log.error("返回报文加密签名失败: {}", e.getMessage());
            ajaxResult.setCode(410);
            ajaxResult.setMsg("加密签名错误");
        }

        return ajaxResult;
    }

}
